/*
    作者：zx
    时间：2022.11.26
    描述：内存初始化，位图管理哪一块内存，页面大小，
*/

#ifndef MEMORY_H
#define MEMORY_H

#include "comm/types.h"
#include "tools/bitmap.h"
#include "ipc/mutex.h"
#include "comm/boot_info.h"

#define MEMORY_EXT_START (1024*1024) 
#define MEMORY_PAGE_SIZE 4096
#define MEMORY_EBDA_START 0x80000
#define MEMORY_TASK_BASE 0x80000000
// shell任务的栈顶
#define MEMORY_TASK_STACK_TOP 0xE0000000
//
#define MEMORY_TASK_STACK_SIZE (500*MEMORY_PAGE_SIZE)
// 进程运行时所需参数的预留空间
#define MEMORY_TASK_ARG_SIZE (4*MEMORY_PAGE_SIZE)
// 因为总共128M内存
#define MEMORY_EXT_END (128 * 1024 * 1024)

typedef struct 
{
    mutex_t mutex;
    uint32_t start;
    uint32_t size;
    // 页面大小
    uint32_t page_size;
    //
    bitmap_t bitmap;
}bitmap_manager_t;
  

// 内存图  
typedef struct 
{
    void * linear_addr_start;
    void * linear_addr_end;
    void * physical_addr_start;
    // 该段内存是否可读写
    uint32_t permission;
}memory_map_t;


void memory_init(boot_info_t * boot_info);
// 创建用户使用的逻辑地址、目前用于创建进程的页表
uint32_t memory_create_user_linear_mem(void);
// 为进程分配页面
int memory_alloc_page_for(uint32_t start_addr, uint32_t alloc_size, int permission);
// 为指定页表分配空间
int memory_alloc_page_for_page_dir(uint32_t page_dir, uint32_t virtual_addr,uint32_t alloc_size, int permission);
// 为进程分配内核栈所需页面, 这里没有分配0x80000000地址，所以物理内存和线性内存是等价的
uint32_t memory_alloc_page(void);
void memory_free_page(uint32_t page_addr);
// 进程复制，复制页表
uint32_t memory_copy_user_linear_mem(uint32_t page_dir);
// 进程销毁，释放页表
void memory_free_user_linear_mem(uint32_t page_dir);
uint32_t memory_get_pyhscial_addr_from_page_dir(uint32_t page_dir, uint32_t vaddr);

// 拷贝当前页表(from_addr)数据进入其他页表(new_page_dir)对应的地址(aim_addr)
int memory_copy_user_linear_mem_data(uint32_t aim_addr, 
                                    uint32_t new_page_dir, 
                                    uint32_t from_addr, 
                                    int size);

//动态分配进程的堆空间
char * sys_sbrk(int incr);
#endif // !MEMORY_H